/**
 * @file:          Protection.c
 * @brief:
 * @details:
 * @author:        wjh
 * @date created:  2023.06.19
 * @version:       1.0.0
 * @par copyright (c):
 *
 * @par history (desc):
 *   version:1.0.0, wjh, 2023.06.19,16:45:44
 */

/* Include Files **************************************************************/
#include "Protection.h"
#include "common.h"
#include "CommunicationInterface.h"

/* Global Variable Define *****************************************************/
const uint8 protection_err_msg[ERR_MAX_SIZE][ERR_MSG_LENGTH] = {
    "EncoderMutation",
    "EncoderReadErr",
    "PeakCurrentOverLimit",
    "ContinueCurrent_OverLimit",
    "HardwareCurrent_OverLimit",
    "SpeedFdbOverLimit",
    "PosFdbOverLimit",
    "PosCmdMutation",
    "ExcessivePosTrackingError",
    "ValueAbnormal",
    "MotorCheckUnStable",
    "MotorCheckNotConnected",
    "MotorCheckResistanceDifferent",
    "MotorCheckOtherErr"};
const uint8 protection_warning_msg[WARN_MAX_SIZE][WARN_MSG_LENGTH] = {
    "CommunicationErr",
    "MotorPowerSupplyTooLow",
    "McuOverHeating",
};

/* Function Define ************************************************************/
uint8 Protection_Init(struct Protection *self)
{
    self->ReportErr = Protection_ReportErr;
    self->ReportWarning = Protection_ReportWarning;
    self->ClearErr = Protection_ClearErr;
    self->ClearWarning = Protection_ClearWarning;
    self->SetErr = Protection_SetErr;
    self->SetWarning = Protection_SetWarning;
    self->UpdateParam = Protection_UpdateParam;
    self->ErrParsing = Protection_ErrParsing;
    self->WarningParsing = Protection_WarningParsing;

    self->UpdateParam(self);

    self->err_msg = protection_err_msg;
    self->warning_msg = protection_warning_msg;
}

void Protection_ReportErr(struct Protection *self)
{
    // TERMINAL_Adv("[%d]:\r\n", self->err_code);
    if (self->param_en && self->param_enable_report == 1)
    {
        if (self->err_code != self->err_code_last)
        {
            TERMINAL_Adv("[%#x]:\r\n", self->err_code);
            for (uint16 i = 0; i < ERR_MAX_SIZE; i++)
            {
                if ((self->err_code ^ self->err_code_last) & PROTECTION_CODE(i))
                {

                    TERMINAL_Adv("%s\r\n", self->err_msg[i]);
                }
            }
        }
    }
}

void Protection_ReportWarning(struct Protection *self)
{
    // TERMINAL_Adv("[%d]:\r\n", self->warning_code);
    if (self->param_en && self->param_enable_report == 1)
    {
        if (self->warning_code != self->warning_code_last)
        {
            TERMINAL_Adv("[%#x]:\r\n", self->warning_code);
            for (uint16 i = 0; i < WARN_MAX_SIZE; i++)
            {
                if ((self->warning_code ^ self->warning_code_last) & PROTECTION_CODE(i))
                {
                    TERMINAL_Adv("%s\r\n", self->warning_msg[i]);
                }
            }
        }
    }
}

void Protection_ClearErr(struct Protection *self, uint16 err_code)
{
    self->err_code &= ~(err_code);
}

void Protection_ClearWarning(struct Protection *self, uint16 warnning_code)
{
    self->warning_code &= ~(warnning_code);
}

void Protection_SetErr(struct Protection *self, uint16 err_code)
{
    self->err_code |= (err_code);
}

void Protection_SetWarning(struct Protection *self, uint16 warnning_code)
{
    self->warning_code |= (warnning_code);
}

void Protection_UpdateParam(struct Protection *self)
{
    self->continuous_overcurrent_count_max = (uint32)(self->param_continuous_overcurrent_time_s / self->param_check_period_s);
    self->continuous_overspeed_count_max = (uint32)(self->param_speed_over_limit_time_s / self->param_check_period_s);
    self->continuous_pos_tracking_error_count_max = (uint32)(self->param_pos_tracking_error_time_s / self->param_check_period_s);
}

void Protection_ErrParsing(struct Protection *self, uint32_t err_code)
{
    TERMINAL_Adv("[%#x]:\r\n", err_code);
    for (uint16 i = 0; i < ERR_MAX_SIZE; i++)
    {
        if (err_code & PROTECTION_CODE(i))
        {
            TERMINAL_Adv("%s\r\n", self->err_msg[i]);
        }
    }
}

void Protection_WarningParsing(struct Protection *self, uint32_t warning_code)
{
    TERMINAL_Adv("[%#x]:\r\n", warning_code);
    for (uint16 i = 0; i < WARN_MAX_SIZE; i++)
    {
        if (warning_code & PROTECTION_CODE(i))
        {
            TERMINAL_Adv("%s\r\n", self->warning_msg[i]);
        }
    }
}